// (C) 2022 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Intel Program License Subscription 
// Agreement, Intel FPGA IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Intel and sold by 
// Intel or its authorized distributors.  Please refer to the applicable 
// agreement for further details.

module synchronizer #(
	parameter USE_INIT_0 = 0,
    parameter WIDTH = 16,
	parameter STAGES = 3
)
(
	input clk_in,arst_in,
	input clk_out,arst_out,
	
	input [WIDTH-1:0] dat_in,
	output [WIDTH-1:0] dat_out	
);

// launch register
reg [WIDTH-1:0] d /* synthesis preserve */;
always @(posedge clk_in or posedge arst_in) begin
	if (arst_in) d <= 0;
	else d <= dat_in;
end

// capture registers
reg [STAGES*WIDTH-1:0] c /* synthesis preserve */;
always @(posedge clk_out or posedge arst_out) begin
	if (arst_out) c <= 0;
	else c <= {c[(STAGES-1)*WIDTH-1:0],d};
end

initial begin
   if (USE_INIT_0 == 1) begin
      d = 0;
      c = 0;
   end
end


assign dat_out = c[STAGES*WIDTH-1:(STAGES-1)*WIDTH];

endmodule